package org.example.curriculum_design_6_16.service.impl;

import org.example.curriculum_design_6_16.entity.vo.Result;
import org.example.curriculum_design_6_16.service.MailService;
import org.example.curriculum_design_6_16.service.RedisService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class MailServiceImpl implements MailService {

    // 获取配置文件中的发件人邮箱地址
    @Value("${spring.mail.username}")
    private String fromMail;

    // 注入邮件发送器
    @Resource
    private JavaMailSender mailSender;

    // 注入 Redis 服务，用于存储验证码
    @Resource
    private RedisService redisService;

    /**
     * 创建并返回一个简单的邮件消息
     *
     * @param recipient 收件人邮箱地址
     * @param subject 邮件标题
     * @param content 邮件内容
     * @return SimpleMailMessage 邮件消息对象
     */
    @Override
    public SimpleMailMessage GenerateEmail(String recipient, String subject, String content) {
        // 校验收件人地址和主题是否为空
        if (recipient == null || recipient.trim().isEmpty()) {
            throw new IllegalArgumentException("收件人邮箱地址不能为空");
        }
        if (subject == null || subject.trim().isEmpty()) {
            throw new IllegalArgumentException("邮件标题不能为空");
        }

        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(fromMail);  // 发件人邮箱
        message.setTo(recipient);   // 收件人邮箱
        message.setSubject(subject); // 邮件标题
        message.setText(content);    // 邮件内容
        return message;
    }

    /**
     * 发送验证码邮件，生成验证码并通过邮件发送给接收人
     *
     * @param recipient 收件人邮箱地址
     * @return 返回操作结果，包括状态码和消息
     */
    @Override
    public Result SignupCodeMail(String recipient) {
        // 校验邮箱地址是否为空
        if (recipient == null || recipient.trim().isEmpty()) {
            return Result.fail(400, "收件人邮箱地址不能为空");
        }
        if(!isValidEmail(recipient)) {
            return Result.fail(412, "邮箱格式无效，请检查邮箱地址");
        }
        try {
            // 生成一个6位数的随机验证码
            String code = String.valueOf(Math.random()).substring(2, 8);

            // 发送带有验证码的邮件
            SendMailSync(recipient, "验证码", "<p>【研究生奖学金评定系统】验证码: (<b>" + code + "</b>)，用于邮箱验证码登录，5分钟内有效。验证码提供给他人可能导致帐号被盗，请勿泄露，谨防被骗。</p>");

            // 尝试将验证码保存到 Redis 中，有效期为300秒（5分钟）
            try {
                redisService.setMailCode(recipient, code, 300);
            } catch (Exception e) {
                // Redis连接失败时，记录日志但不影响邮件发送
                System.out.println("Redis连接失败，验证码无法缓存: " + e.getMessage());
                // 返回成功，但提示用户验证码可能无法正常验证
                return Result.success("验证码已发送，但系统暂时无法验证，请联系管理员");
            }

            // 返回成功结果
            return Result.success(code);
        } catch (MailException e) {
            // 发送邮件失败时返回错误结果
            return Result.fail(500, "邮件发送失败，请重试！");
        }
    }

    @Override
    public Result RetrieveCodeMail(String recipient) {
        // 校验邮箱地址是否为空
        if (recipient == null || recipient.trim().isEmpty()) {
            return Result.fail(400, "收件人邮箱地址不能为空");
        }
        if(!isValidEmail(recipient)) {
            return Result.fail(412, "邮箱格式无效，请检查邮箱地址");
        }
        try {
            // 生成一个6位数的随机验证码
            String code = String.valueOf(Math.random()).substring(2, 8);

            // 发送带有验证码的邮件
            SendMailSync(recipient, "验证码", "<p>【研究生奖学金评定系统】验证码: (<b>" + code + "</b>)，用于找回密码，5分钟内有效。验证码提供给他人可能导致帐号被盗，请勿泄露，谨防被骗。</p>");

            // 尝试将验证码保存到 Redis 中，有效期为300秒（5分钟）
            try {
                redisService.setMailCode(recipient, code, 300);
            } catch (Exception e) {
                // Redis连接失败时，记录日志但不影响邮件发送
                System.out.println("Redis连接失败，验证码无法缓存: " + e.getMessage());
                // 返回成功，但提示用户验证码可能无法正常验证
                return Result.success("验证码已发送，但系统暂时无法验证，请联系管理员");
            }

            // 返回成功结果
            return Result.success(code);
        } catch (MailException e) {
            // 发送邮件失败时返回错误结果
            return Result.fail(500, "邮件发送失败，请重试！");
        }
    }

    /**
     * 校验邮箱格式是否有效
     * @param email 邮箱地址
     * @return 是否有效
     */
    private boolean isValidEmail(String email) {
        String emailRegex = "^[A-Za-z0-9+_.-]+@([A-Za-z0-9.-]+\\.)+[A-Za-z]{2,}$";
        Pattern pattern = Pattern.compile(emailRegex);
        Matcher matcher = pattern.matcher(email);
        return matcher.matches();
    }

    /**
     * 异步发送邮件，避免阻塞主线程
     *
     * @param recipient 收件人邮箱地址
     * @param subject 邮件标题
     * @param content 邮件内容
     */
    @Async
    public void SendMailSync(String recipient, String subject, String content) {
        // 校验邮箱地址是否为空
        if (recipient == null || recipient.trim().isEmpty()) {
            System.out.println("发送邮件失败: 收件人邮箱地址不能为空");
            return;
        }
        // 校验主题和内容是否为空
        if (subject == null || subject.trim().isEmpty()) {
            System.out.println("发送邮件失败: 邮件标题不能为空");
            return;
        }
        if (content == null || content.trim().isEmpty()) {
            System.out.println("发送邮件失败: 邮件内容不能为空");
            return;
        }

        try {
            // 发送邮件
            mailSender.send(GenerateEmail(recipient, subject, content));
        } catch (MailException e) {
            // 发送邮件失败时打印错误日志
            System.out.println("发送邮件失败: " + e.getMessage());
            e.printStackTrace();  // 输出异常堆栈信息以便调试
        }
    }
}
